/*
 * Copyright 2009-2010 Belmont Software Services
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.belmont.backup.gui;

import java.io.*;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.awt.*;
import java.awt.event.*;
import java.sql.SQLException;
import javax.swing.event.*;
import javax.swing.*;
import javax.swing.tree.*;
import org.jdesktop.layout.*;
import com.belmont.backup.*;

public class BNRGuiView implements IBackupConstants, WindowListener, ListSelectionListener, ChangeListener {
    /* backup ui items */
    JTextField backupDir = new JTextField();
    JButton backupAdd = new JButton();
    JButton backupAddDir = new JButton("Add");
    JButton backupDelete = new JButton();
    JButton backupStart = new JButton();
    JPanel backupWizard = new JPanel();
    CardLayout backupCards = new CardLayout();
    JList backupList = new JList();
    ActionListener backupNextListener;
    ActionListener backupPrevListener;
    JList includeList = new JList();
    JList excludeList = new JList();
    JTextField excludeFilter = new JTextField();
    JTextField includeFilter = new JTextField();
    Vector<String> includeFilters = new Vector<String>();
    Vector<String> excludeFilters = new Vector<String>();
    JButton addInclude = new JButton("+");
    JButton delInclude = new JButton("-");
    JButton addExclude = new JButton("+");
    JButton delExclude = new JButton("-");

    /* restore ui items */
    JCheckBox selectAll = new JCheckBox();
    JButton restoreStart = new JButton();
    JList restoreDirs = new JList();
    JList restoreVersions = new JList();
    JTree restoreTree = new JTree();
    JTextField dir = new JTextField();
    JButton dirChange = new JButton();
    JScrollPane treeView = new JScrollPane();
    CheckBoxNodeRenderer renderer = new CheckBoxNodeRenderer();
    JPanel restoreWizard = new JPanel();
    CardLayout restoreCards = new CardLayout();
    ActionListener restoreNextListener;
    ActionListener restorePrevListener;

    /* status ui items */
    JLabel nextSched = new JLabel();
    JLabel backupServer = new JLabel();
    JProgressBar progressBar = new JProgressBar();
    JLabel currentTask = new JLabel();
    JLabel currentOperation = new JLabel();
    JLabel currentFile = new JLabel();
    JLabel filesToTransfer = new JLabel();
    JLabel filesTransferred = new JLabel();
    JLabel amountToTransfer = new JLabel();
    JLabel amountTransferred = new JLabel();
    JButton cancel = new JButton();
    JButton viewLog = new JButton();

    /* info ui items */

    JLabel nextBackup = new JLabel();
    JLabel backupSchedule = new JLabel();				       
    JLabel lastBackup = new JLabel();
    JLabel lastBackupDir = new JLabel();
    JLabel userDirEnabled = new JLabel();

    JLabel msgLabel = new JLabel();

    JDialog aboutBox;
    ChooseDirDialog dirChooser;

    int backupIndex;
    int restoreIndex;
    int statusIndex;
    int infoIndex;
    JTabbedPane tabPane;
    JFrame      frame;
    GuiMain     main;

    public BNRGuiView(GuiMain main) {
        this.main = main;
    }

    public void start() {
        if (frame == null) {
            createUI();
            frame = new JFrame();
            frame.addWindowListener(this);
            //frame.setSize(new Dimension(720, 435));
            frame.setLayout(new BorderLayout());
            frame.add(tabPane, BorderLayout.CENTER);
            frame.setResizable(false);
            JPanel msgPanel = new JPanel();
            msgLabel.setForeground(Color.RED);
            print(null);
            msgPanel.add(msgLabel);
            msgPanel.setMinimumSize(new Dimension(200, 30));
            frame.add(msgPanel, BorderLayout.SOUTH);
            setBackupPanel();
            frame.setSize(new Dimension(820, 540));
        }
    }

    public void show() {
        frame.show();
    }

    public void hide() {
        frame.hide();
    }

    void createUI() {
        tabPane = new JTabbedPane();
        tabPane.add("Backup", createBackupPanel());
        backupIndex = 0;
        tabPane.add("Restore", createRestorePanel());
        restoreIndex = 1;
        tabPane.add("Status", createStatusPanel());
        statusIndex = 2;
        /*
          tabPane.add("Info", createInfoPanel());
          infoIndex = 3;
        */
        tabPane.addChangeListener(this);
        frame = new JFrame(main.app.getString("name", main.company+" Backup Service"));
        frame.add(tabPane);
    }

    void buildRestoreTree() {
        try {
            restoreTree = new JTree(main.app.getTreeData(main.restorePath, main.backupname));
            restoreTree.setCellRenderer(renderer);
            restoreTree.setCellEditor(new CheckBoxNodeEditor(restoreTree));
            restoreTree.setEditable(true);
            treeView.setViewportView(restoreTree);
        } catch (SQLException ex) {
            Utils.log(LOG_ERROR, "Error building restore tree", ex);
        }
    }

    JPanel createWizardStep(ActionListener plistener,
                            String nextText,
                            ActionListener nlistener,
                            String helpText,
                            JComponent component) {
        JPanel p = new JPanel();
        p.setBorder(BorderFactory.createEtchedBorder());
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(p);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);
        p.setLayout(layout);
        //JLabel help = new JLabel();
        JTextArea help = new JTextArea(helpText, 2, 30);
        help.setLineWrap(true);
        help.setWrapStyleWord(true);
        help.setBackground(p.getBackground());
        //help.setText(helpText);

        JButton nextButton = new JButton();
        nextButton.setText(nextText);
        nextButton.addActionListener(nlistener);

        JButton prevButton = new JButton();

        prevButton.setText("<< Back");
        if (plistener == null) {
            prevButton.setEnabled(false);
        } else {
            prevButton.setEnabled(true);
            prevButton.addActionListener(plistener);
        }

        JLabel gap = new JLabel();
        gap.setMinimumSize(new Dimension(320, 30));
        layout.setHorizontalGroup(layout.createParallelGroup()
                                  .add(help)
                                  .add(component)
                                  .add(layout.createSequentialGroup()
                                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(prevButton))
                                       .add(gap)
                                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                            .add(nextButton))));
        layout.setVerticalGroup(layout.createSequentialGroup()
                                .add(help)
                                .add(component)
                                .add(layout.createParallelGroup()
                                     .add(prevButton)
                                     .add(gap)
                                     .add(nextButton)));

        return p;
    }

    void createRestoreWizard() {
        restoreWizard.setLayout(restoreCards);

        restoreNextListener = new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    print(null);
                    restoreCards.next(restoreWizard);
                }
            };

        restorePrevListener = new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    print(null);
                    restoreCards.previous(restoreWizard);
                }
            };

        ActionListener pickVersionListener = new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    if (restoreDirs.getMinSelectionIndex() >= 0) {
                        print(null);
                        main.getRestoreVersions();
                        restoreCards.next(restoreWizard);
                    } else {
                        print("No path selected to restore.");
                    }
                }
            };

        ActionListener pickFilesListener = new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    if (restoreVersions.getMinSelectionIndex() >= 0) {
                        print(null);
                        main.getManifest();
                        buildRestoreTree();
                        restoreCards.next(restoreWizard);
                    } else {
                        print("No version selected to restore.");
                    }
                }
            };

        JScrollPane dirsView = new JScrollPane();
        restoreDirs.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        dirsView.setViewportView(restoreDirs);
        restoreWizard.add(createWizardStep(null,
                                           "Next >>", pickVersionListener,
                                           "Select directory to restore:", dirsView), "Step 1");
        JScrollPane versionsView = new JScrollPane();

        restoreVersions.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        versionsView.setViewportView(restoreVersions);
        restoreWizard.add(createWizardStep(restorePrevListener,
                                           "Next >>", pickFilesListener,
                                           "Select which backup date to restore:", versionsView), "Step 2");

        JPanel tp = new JPanel();
        tp.setLayout(new BorderLayout());
        treeView.setViewportView(restoreTree);
        tp.add(treeView,"Center");
        selectAll.setText(main.app.getString("restoreSelectAll.text"));
        selectAll.setToolTipText(main.app.getString("restoreSelectAll.toolTipText"));
        selectAll.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    selectAllActionPerformed(evt);
                }
            });
        tp.add(selectAll,"South");

        restoreWizard.add(createWizardStep(restorePrevListener,
                                           "Next >>", restoreNextListener,
                                           "Select which files to restore:", tp), "Step 3");

        JPanel dp = new JPanel();
        dirChange.setText("Browse...");
        dirChange.setToolTipText(main.app.getString("restoreChangeDir.toolTipText"));
        dirChange.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    dirChangeActionPerformed(evt);
                }
            });
        dir.setColumns(40);
        dp.add(dir);
        dp.add(dirChange);	
        restoreWizard.add(createWizardStep(restorePrevListener,
                                           "Next >>", restoreNextListener,
                                           "Select directory to restore to:", dp), "Step 4");	


        JPanel lp = new JPanel();
        lp.setLayout(new BorderLayout());
        JLabel l = new JLabel();
	
        l.setText(" ");
        lp.add(l, "Center");
        restoreWizard.add(createWizardStep(restorePrevListener,
                                           "Start Restore",
                                           new java.awt.event.ActionListener() {
                                               public void actionPerformed(java.awt.event.ActionEvent evt) {
                                                   restoreStartActionPerformed(evt);
                                               }
                                           },
                                           "Select Start to begin restore operation.", lp), "Step 5");	
	
    }

    JPanel createIncludePanel() {
        JPanel includePanel = new JPanel();
        includePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),"Include Filters:"));
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(includePanel);
        includePanel.setLayout(layout);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);
        includeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JScrollPane includeView = new JScrollPane();
        includeView.setViewportView(includeList);
        addInclude.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    addFilter(includeFilter.getText(), includeFilters);
                }
            });
        delInclude.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    delFilter(includeList, includeFilters);
                }
            });
        JLabel fl = new JLabel("Filter:");

        layout.setHorizontalGroup(layout.createSequentialGroup()
                                  .add(layout.createParallelGroup()
                                       .add(includeView)
                                       .add(layout.createSequentialGroup()
                                            .add(fl)
                                            .add(includeFilter)))
                                  .add(layout.createParallelGroup()
                                       .add(addInclude)
                                       .add(delInclude)));

        layout.setVerticalGroup(layout.createSequentialGroup()
                                .add(layout.createParallelGroup()
                                     .add(includeView)
                                     .add(layout.createSequentialGroup()
                                          .add(addInclude)
                                          .add(delInclude)))
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                     .add(fl)
                                     .add(includeFilter)));
        return includePanel;
    }

    void addFilter(String f, Vector<String> filters) {
        if (f != null) {
            f = f.trim();
            if (f.length() > 0) {
                if (! filters.contains(f)) {
                    filters.addElement(f);
                    setFilters();
                }
            }
        }
    }

    void delFilter(JList list, Vector<String> filter) {
        int idx = list.getMinSelectionIndex();
        if (idx != -1) {
            String f = (String)list.getSelectedValue();
            filter.removeElement(f);
            setFilters();
        }
    }

    JPanel createExcludePanel() {
        JPanel excludePanel = new JPanel();
        excludePanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createEtchedBorder(),"Exclude Filters:"));
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(excludePanel);
        excludePanel.setLayout(layout);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);
        excludeList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        JScrollPane excludeView = new JScrollPane();
        excludeView.setViewportView(excludeList);
        addExclude.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    addFilter(excludeFilter.getText(), excludeFilters);
                }
            });
        delExclude.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    delFilter(excludeList, excludeFilters);
                }
            });

        JLabel fl = new JLabel("Filter:");

        layout.setHorizontalGroup(layout.createSequentialGroup()
                                  .add(layout.createParallelGroup()
                                       .add(excludeView)
                                       .add(layout.createSequentialGroup()
                                            .add(fl)
                                            .add(excludeFilter)))
                                  .add(layout.createParallelGroup()
                                       .add(addExclude)
                                       .add(delExclude)));

        layout.setVerticalGroup(layout.createSequentialGroup()
                                .add(layout.createParallelGroup()
                                     .add(excludeView)
                                     .add(layout.createSequentialGroup()
                                          .add(addExclude)
                                          .add(delExclude)))
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                     .add(fl)
                                     .add(excludeFilter)));

        return excludePanel;
    }

    void createBackupWizard() {
        backupWizard.setLayout(backupCards);

        backupNextListener = new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    print(null);
                    backupCards.next(backupWizard);
                }
            };

        backupPrevListener = new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    print(null);
                    backupCards.previous(backupWizard);
                }
            };


        JPanel p = new JPanel();
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(p);
        p.setLayout(layout);
        //layout.setAutocreateGaps(true);
        //layout.setAutocreateContainerGaps(true);

        JScrollPane listView = new JScrollPane();

        backupAdd.setText(main.app.getString("backupAdd.text"));
        backupAdd.setToolTipText(main.app.getString("backupAdd.toolTipText"));
        backupAdd.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    backupAddActionPerformed(evt);
                }
            });

        backupDelete.setText(main.app.getString("backupDelete.text"));
        backupDelete.setToolTipText(main.app.getString("backupDelete.toolTipText"));
        backupDelete.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    backupDeleteActionPerformed(evt);
                }
            });

        backupStart.setText(main.app.getString("backupStart.text"));
        backupStart.setToolTipText(main.app.getString("backupStart.toolTipText"));
        backupStart.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    backupStartActionPerformed(evt);
                }
            });

        backupList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
        backupList.setListData(main.getBackupListData());
        backupList.addListSelectionListener(this);
        backupList.setToolTipText(main.app.getString("backupList.toolTipText"));
        listView.setViewportView(backupList);

        backupAddDir.setToolTipText("Add directory specified in the text field");
        backupAddDir.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    backupAddDirActionPerformed(evt);
                }
            });

        JPanel bhp = new JPanel();
        FlowLayout flow = new FlowLayout(FlowLayout.LEFT, 4, 4);
        bhp.setLayout(flow);
        backupDir.setColumns(40);
        bhp.add(backupDir);
        bhp.add(backupAddDir);

        /*
          layout.setHorizontalGroup(layout.createSequentialGroup()
          .add(layout.createParallelGroup()
          .add(layout.createSequentialGroup()
          .add(backupDir)
          .add(layout.createParallelGroup()
          .add(backupAddDir)
          .add(backupAdd)))
          .add(listView))
          .add(backupDelete));
        */
        layout.setHorizontalGroup(layout.createParallelGroup()
                                  .add(bhp)
                                  .add(layout.createSequentialGroup()
                                       .add(listView)
                                       .add(layout.createParallelGroup()
                                            .add(backupAdd)
                                            .add(backupDelete))));

        layout.setVerticalGroup(layout.createSequentialGroup()
                                .add(bhp)
                                .add(layout.createParallelGroup()
                                     .add(listView)
                                     .add(layout.createSequentialGroup()
                                          .add(backupAdd)
                                          .add(backupDelete))));

        ActionListener startBackupListener = new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    backupStartActionPerformed(evt);
                }
            };

        backupWizard.add(createWizardStep(null,
                                          "Next >>",
                                          new java.awt.event.ActionListener() {
                                              public void actionPerformed(java.awt.event.ActionEvent evt) {
                                                  if (main.backupList == null || main.backupList.size() == 0) {
                                                      print("No directories to backup");
                                                  } else {
                                                      print(null);
                                                      backupCards.next(backupWizard);
                                                  }
                                              }
                                          },
                                          "Select directory to backup:", p), "Step 1");
	


        p = new JPanel();
        layout = new org.jdesktop.layout.GroupLayout(p);
        p.setLayout(layout);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);
        JPanel ipanel = createIncludePanel();
        JPanel epanel = createExcludePanel();

        layout.setHorizontalGroup(layout.createSequentialGroup()
                                  .add(ipanel)
                                  .add(epanel));

        layout.setVerticalGroup(layout.createParallelGroup()
                                .add(ipanel)
                                .add(epanel));
	

        backupWizard.add(createWizardStep(backupPrevListener,
                                          "Next >>", backupNextListener,
                                          "Set any include/exclude filters which control which files are included in or excluded from the backup. Filters set by the administrator cannot be deleted.", p), "Step 2");


        p = new JPanel();
        layout = new org.jdesktop.layout.GroupLayout(p);
        p.setLayout(layout);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);
        JLabel onceLabel = new JLabel("Run once");
        JLabel hourLabel = new JLabel("Hours");
        JLabel dayLabel = new JLabel("Days");

        JPanel lp = new JPanel();
        lp.setLayout(new BorderLayout());
        JLabel l = new JLabel();
	
        l.setText(" ");
        lp.add(l, "Center");
        backupWizard.add(createWizardStep(backupPrevListener,
                                          "Start backup",
                                          startBackupListener,
                                          "Select Start to begin backup operation.", lp), "Step 3");	
    }

    JPanel createBackupPanel() {
        JPanel p = new JPanel();
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(p);
        p.setLayout(layout);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);

        JButton icon = createIconButton();
        JLabel title = new JLabel("Backup Directories");
        title.setFont(new Font("Lucida Grande", Font.PLAIN, 24));

        JLabel desc = new JLabel(main.app.getString("backup.text"));
        createBackupWizard();

        layout.setHorizontalGroup(layout.createSequentialGroup()
                                  .add(icon)
                                  .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(title)
                                            .add(desc))
                                       .add(backupWizard)));

        layout.setVerticalGroup(layout.createParallelGroup()
                                .add(icon)
                                .add(layout.createSequentialGroup()
                                     .add(title)
                                     .add(desc)
                                     .add(backupWizard)));

        return p;
    }


    JPanel createInfoPanel() {
        JPanel p = new JPanel();
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(p);
        p.setLayout(layout);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);

        JButton icon = createIconButton();
        JLabel title = new JLabel("Information and Application Options");
        title.setFont(new Font("Lucida Grande", Font.PLAIN, 24));

        JLabel desc = new JLabel(main.app.getString("info.text"));
        Dimension minL = new Dimension(120, 20);
        JLabel nextBackupLabel = new JLabel("Next scheduled backup:");
        nextBackupLabel.setMinimumSize(minL);
        JLabel backupScheduleLabel = new JLabel("Backup schedule:");
        backupScheduleLabel.setMinimumSize(minL);
        JLabel lastBackupLabel = new JLabel("Last backup on:");
        lastBackupLabel.setMinimumSize(minL);
        JLabel lastBackupDirLabel = new JLabel("Last directory backed up:");
        lastBackupDirLabel.setMinimumSize(minL);
        JLabel userDirEnabledLabel = new JLabel("Admin allows user backups:");
        userDirEnabledLabel.setMinimumSize(minL);

        layout.setHorizontalGroup(layout.createSequentialGroup()
                                  .add(icon)
                                  .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(title)
                                            .add(desc))
                                       .add(layout.createSequentialGroup()
                                            .add(layout.createParallelGroup()
                                                 .add(nextBackupLabel)
                                                 .add(backupScheduleLabel)
                                                 .add(lastBackupLabel)
                                                 .add(lastBackupDirLabel)
                                                 .add(userDirEnabledLabel))
                                            .add(layout.createParallelGroup()
                                                 .add(nextBackup)
                                                 .add(backupSchedule)
                                                 .add(lastBackup)
                                                 .add(lastBackupDir)
                                                 .add(userDirEnabled)))));

        layout.setVerticalGroup(layout.createParallelGroup()
                                .add(icon)
                                .add(layout.createSequentialGroup()
                                     .add(title)
                                     .add(desc)
                                     .add(layout.createSequentialGroup()
                                          .add(layout.createParallelGroup()
                                               .add(nextBackupLabel)
                                               .add(nextBackup))
                                          .add(layout.createParallelGroup()
                                               .add(backupScheduleLabel)
                                               .add(backupSchedule))
                                          .add(layout.createParallelGroup()
                                               .add(lastBackupLabel)
                                               .add(lastBackup))
                                          .add(layout.createParallelGroup()
                                               .add(lastBackupDirLabel)
                                               .add(lastBackupDir))
                                          .add(layout.createParallelGroup()
                                               .add(userDirEnabledLabel)
                                               .add(userDirEnabled)))));

        return p;
    }
   

    JPanel createRestorePanel() {
        JPanel p = new JPanel();
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(p);
        p.setLayout(layout);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);

        JButton icon = createIconButton();
        JLabel title = new JLabel("Restore Directories");
        title.setFont(new Font("Lucida Grande", Font.PLAIN, 24));

        JLabel desc = new JLabel(main.app.getString("restore.text"));
        createRestoreWizard();


        layout.setHorizontalGroup(layout.createSequentialGroup()
                                  .add(icon)
                                  .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(title)
                                            .add(desc))
                                       .add(restoreWizard)));

        layout.setVerticalGroup(layout.createParallelGroup()
                                .add(icon)
                                .add(layout.createSequentialGroup()
                                     .add(title)
                                     .add(desc)
                                     //				     .add(50, 50, 50)
                                     .add(restoreWizard)));

        return p;
    }

    JButton createIconButton() {
        JButton icon = new JButton();
        Insets insets = new Insets(2,2,2,2);
        //icon.setMaximumSize(new Dimension(80, 80));
        String ipath = main.app.getString("icon.path");
        if (main.logoURL != null && main.logoURL.startsWith("http://")) {
            ipath = main.logoURL;
        }
        icon.setIcon(main.createImageIcon(ipath));
        icon.setFocusPainted(false);
        icon.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    showAboutBox();
                }
            });
        icon.setMargin(insets);
        return icon;
    }

    void setServerStatus() {
        String srv = main.app.getServerURL();
        backupServer.setText(srv + " [" + (main.app.getConnected() ? "CONNECTED]" : "NOT CONNECTED]"));
    }

    JPanel createStatusPanel() {
        JPanel p = new JPanel();
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(p);
        p.setLayout(layout);
        layout.setAutocreateGaps(true);
        layout.setAutocreateContainerGaps(true);


        JButton icon = createIconButton();
        JLabel title = new JLabel("Status");
        title.setFont(new Font("Lucida Grande", Font.PLAIN, 24));

        Dimension minL = new Dimension(120, 20);

        JLabel desc = new JLabel("<html>Displays the status of the currently running backup or restore operation.</html>");
        JLabel currentFileLabel = new JLabel("Current File:");
        JLabel filesToTransferLabel = new JLabel("Files to Transfer:");
        JLabel filesTransferredLabel = new JLabel("Files Transferred:");
        JLabel amountToTransferLabel = new JLabel("Amount to transfer:");
        JLabel amountTransferredLabel = new JLabel("Amount Transferred:");
        JPanel spacer = new JPanel();
        JLabel currentOperationLabel = new JLabel("Current Operation:");
        JLabel currentTaskLabel = new JLabel("Task:");
        JLabel nextSchedLabel = new JLabel("Next scheduled backup:");
        JLabel backupServerLabel = new JLabel("Backup server:");

        setServerStatus();
        nextSched.setText("None scheduled");
        viewLog.setText("View Log...");
        viewLog.setToolTipText(main.app.getString("viewlog.toolTipText"));
        viewLog.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    viewLogActionPerformed(evt);
                }
            });

        cancel.setText("Cancel");
        //cancel.setEnabled(false);
        cancel.setToolTipText(main.app.getString("cancel.toolTipText"));
        cancel.addActionListener(new java.awt.event.ActionListener() {
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    cancelActionPerformed(evt);
                }
            });

        nextSchedLabel.setMinimumSize(minL);
        currentTaskLabel.setMinimumSize(minL);
        currentOperationLabel.setMinimumSize(minL);
        currentFileLabel.setMinimumSize(minL);
        filesToTransferLabel.setMinimumSize(minL);
        filesTransferredLabel.setMinimumSize(minL);
        amountToTransferLabel.setMinimumSize(minL);
        amountTransferredLabel.setMinimumSize(minL);

        progressBar.setDoubleBuffered(true);
        progressBar.setStringPainted(true);
        layout.setHorizontalGroup(layout.createSequentialGroup()
                                  .add(icon)
                                  .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                       .add(layout.createParallelGroup()
                                            .add(title)
                                            .add(desc))
                                       .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
                                            .add(progressBar)
                                            .add(layout.createSequentialGroup()
                                                 .add(backupServerLabel)
                                                 .add(backupServer))
                                            .add(layout.createSequentialGroup()
                                                 .add(nextSchedLabel)
                                                 .add(nextSched))
                                            .add(layout.createSequentialGroup()
                                                 .add(currentTaskLabel)
                                                 .add(currentTask))
                                            .add(layout.createSequentialGroup()
                                                 .add(currentOperationLabel)
                                                 .add(currentOperation))
                                            .add(layout.createSequentialGroup()
                                                 .add(currentFileLabel)
                                                 .add(currentFile))
                                            .add(layout.createSequentialGroup()
                                                 .add(filesToTransferLabel)
                                                 .add(filesToTransfer))
                                            .add(layout.createSequentialGroup()
                                                 .add(filesTransferredLabel)
                                                 .add(filesTransferred))
                                            .add(layout.createSequentialGroup()
                                                 .add(amountToTransferLabel)
                                                 .add(amountToTransfer))
                                            .add(layout.createSequentialGroup()
                                                 .add(amountTransferredLabel)
                                                 .add(amountTransferred)))
                                       .add(spacer)
                                       .add(viewLog)
                                       .add(cancel))
                                  .addContainerGap());

        layout.setVerticalGroup(layout.createParallelGroup()
                                .add(icon)
                                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.TRAILING)
                                     .add(layout.createSequentialGroup()
                                          .add(title)
                                          .add(desc)
                                          //					  .add(50, 50, 50)
                                          .add(progressBar)
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(backupServerLabel)
                                               .add(backupServer))
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(nextSchedLabel)
                                               .add(nextSched))
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(currentTaskLabel)
                                               .add(currentTask))
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(currentOperationLabel)
                                               .add(currentOperation))
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(currentFileLabel)
                                               .add(currentFile))
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(filesToTransferLabel)
                                               .add(filesToTransfer))
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(filesTransferredLabel)
                                               .add(filesTransferred))
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(amountToTransferLabel)
                                               .add(amountToTransfer))
                                          .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
                                               .add(amountTransferredLabel)
                                               .add(amountTransferred))
                                          .add(spacer)
                                          .add(viewLog)
                                          .add(cancel))));
    
        return p;
    }


    public void showAboutBox() {
        if (aboutBox == null) {
            aboutBox = new AboutBox(main, main.frame);
            aboutBox.setLocationRelativeTo(main.frame);
        }
        aboutBox.show();
    }

    public void showDirChooser(String title) {
        if (dirChooser == null) {
            dirChooser = new ChooseDirDialog(main.frame, true);
            dirChooser.setLocationRelativeTo(main.frame);
        }
        dirChooser.setTitle(title);
        dirChooser.dir = null;
        dirChooser.show();
    }

    public void valueChanged(ListSelectionEvent evt) {
        if (evt.getSource() == backupList) {
            int idx = backupList.getMinSelectionIndex();
            backupDelete.setEnabled(idx != -1);
            if (idx != -1) {
                Object dirs[] = backupList.getSelectedValues();
                if (dirs.length > 0) {
                    backupDir.setText((String)dirs[0]);
                }
            }
        }
    }

    public void	windowActivated(WindowEvent e) {
    }

    public void	windowClosed(WindowEvent e) {
    }

    public void	windowClosing(WindowEvent e) {
        main.stop();
    }

    public void	windowDeactivated(WindowEvent e) {
    }

    public void	windowDeiconified(WindowEvent e) {
    }

    public void	windowIconified(WindowEvent e) {
    }

    public void	windowOpened(WindowEvent e) {
    }

    public void print(String msg) {
        if (msg == null) {
            msgLabel.setText("       ");
        } else {
            System.out.println(msg);
            msgLabel.setText(msg);
        }
    }

    public void	stateChanged(ChangeEvent e)  {
        if (e.getSource() == tabPane) {
            print(null);
            main.refreshConfig();
            // build restore tree
            int sel = tabPane.getSelectedIndex();
            if (sel == restoreIndex) {
                setRestorePanel();
            } else if (sel == backupIndex) {
                setBackupPanel();
            }
        }
    }

    void setRestorePanel() {
        main.getRestoreDirectories();
        String defaultDir = main.app.getString(CONFIG_RESTORE_DIRECTORY, null);

        if (defaultDir == null) {
            defaultDir = main.server.getConfig().getRestoreDirectory();
        }

        if (defaultDir == null) {
            defaultDir = main.app.getString(CONFIG_DEFAULT_RESTORE_DIRECTORY, null);
        }

        if (defaultDir != null) {
            dir.setText(defaultDir);
        }
        selectAll.setSelected(false);
        restoreCards.first(restoreWizard);
    }

    String[] mergeFilters(boolean allowed, String cf[], Vector<String> filters) {
        if (!allowed) {
            if (cf == null) {
                return new String[0];
            } else {
                return cf;
            }
        }
        filters = (Vector<String>)filters.clone();
        int s = filters.size();
        if (s == 0) {
            if (cf == null) {
                return new String[0];
            } else {
                return cf;
            }
        }
        if (cf != null) {
            for (int i=0; i < cf.length; i++) {
                if (! filters.contains(cf[i])) {
                    filters.addElement(cf[i]);
                }
            }
        }
        String f[] = new String[filters.size()];
        for (int i=0; i < f.length; i++) {
            f[i] = filters.elementAt(i);
        }

        return f;
    }

    void setFilters() {
        Config config = main.server.getConfig();

        String cf[] = config.getDefaultIncludeFilter();
        boolean allowed = config.getAllowBackupDirChange();
        String f[] = mergeFilters(allowed, cf, includeFilters);
        main.app.setIncludeFilter(f);
        includeList.setListData(f);
        cf = config.getDefaultExcludeFilter();
        f = mergeFilters(allowed, cf, excludeFilters);
        main.app.setExcludeFilter(f);
        excludeList.setListData(f);
        setDirChangeUI(config);
    }

    void setBackupPanel() {
        setFilters();
        backupCards.first(backupWizard);
    }

    void setDirChangeUI(Config config) {
        boolean allowed = config.getAllowBackupDirChange();
        backupAdd.setEnabled(allowed);
        backupAddDir.setEnabled(allowed);
        backupDelete.setEnabled(allowed);
        addInclude.setEnabled(allowed);
        delInclude.setEnabled(allowed);
        addExclude.setEnabled(allowed);
        delExclude.setEnabled(allowed);
    }

    private void dirChangeActionPerformed(java.awt.event.ActionEvent evt) {
        print(null);
        showDirChooser("Select a Restore Directory:");
        if (dirChooser.dir != null) {
            dir.setText(dirChooser.dir.getAbsolutePath());
        }
    }

    void resetStatus() {
        tabPane.setEnabledAt(backupIndex, true);
        tabPane.setEnabledAt(restoreIndex, true);
        cancel.setEnabled(false);
        cancel.setText(main.app.getString("cancel.text"));
    }

    void cancelActionPerformed(java.awt.event.ActionEvent evt) {
        print(null);
        main.cancelBackup();
        resetStatus();
    }                                             

    void viewLogActionPerformed(java.awt.event.ActionEvent evt) {
        print(null);
        new ViewLogDialog(main.frame).show();
    }                                             

    void backupStartActionPerformed(java.awt.event.ActionEvent evt) {
        print(null);
        if (main.startBackup()) {
            cancel.setEnabled(true);
            cancel.setText(main.app.getString("cancelBackup.text"));
            tabPane.setSelectedIndex(statusIndex);
            tabPane.setEnabledAt(backupIndex, false);
            tabPane.setEnabledAt(restoreIndex, false);
        }
    }                                             

    private void backupAddDirActionPerformed(java.awt.event.ActionEvent evt) {
        print(null);
        File dir = new File(backupDir.getText());
        if (dir.isDirectory() && dir.exists()) {
            if (main.addBackupDirectory(dir)) {
                backupList.setListData(main.getBackupListData());
            }
        } else {
            print("No valid directory specified.");
        }
    }                                             

    private void backupAddActionPerformed(java.awt.event.ActionEvent evt) {
        print(null);
        showDirChooser("Select directory to backup");
        if (dirChooser.dir != null) {
            if (main.addBackupDirectory(dirChooser.dir)) {
                backupList.setListData(main.getBackupListData());
                backupList.setSelectedIndex(0);
            }
        }
    }                                             

    private void backupDeleteActionPerformed(java.awt.event.ActionEvent evt) {
        print(null);
        Object dirs[] = backupList.getSelectedValues();
        if (dirs.length > 0) {
            if (main.delBackupDirectories(dirs)) {
                backupList.setListData(main.getBackupListData());
            }		
        }
    }

    void restoreStartActionPerformed(java.awt.event.ActionEvent evt) {
        print(null);
        if (main.startRestore()) {
            cancel.setEnabled(true);
            cancel.setText(main.app.getString("cancelRestore.text"));
            tabPane.setSelectedIndex(statusIndex);
            tabPane.setEnabledAt(backupIndex, false);
            tabPane.setEnabledAt(restoreIndex, false);
        }
    }

    private void selectAllActionPerformed(ActionEvent e) {
        print(null);
        restoreTree.collapseRow(0); // forces tree to redisplay
        for (int i = 0; i < restoreTree.getRowCount(); i++) {
            restoreTree.expandRow(i);
        }

        boolean selected = selectAll.isSelected();
        for (int i = 0; i < restoreTree.getRowCount(); i++)  {
            Object node = restoreTree.getPathForRow(i).getLastPathComponent();
            if ((node != null) && (node instanceof DefaultMutableTreeNode))	{
                DefaultMutableTreeNode treeNode = (DefaultMutableTreeNode) node;
                Object userObject = treeNode.getUserObject();
                if ((treeNode.isLeaf()) && (userObject instanceof CheckBoxNode)) {
                    ((CheckBoxNode) userObject).setSelected(selected);
                }
            }
        }
    }
}
